package cn.edu.nit.sys.socket;


import cn.edu.nit.sys.config.WebSocketConfig;
import cn.edu.nit.sys.entity.Message;
import cn.edu.nit.sys.mapper.NoticeMapper;
import cn.edu.nit.sys.mapper.UserMapper;
import cn.edu.nit.sys.utils.SpringBeanUtils;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author 罗文斌
 * @Date 2023/5/16
 * @Version 1.0.0
 */
// @ServerEndpoint(value = "/socket/{id}")
@Component
@Slf4j
public class MessageSocketHandler extends AbstractWebSocketHandler {

    // private static ConcurrentHashMap<String, Session> sessionMap = new ConcurrentHashMap<>();
    private static ConcurrentHashMap<String, WebSocketSession> sessionMap = new ConcurrentHashMap<>();

    private static String id;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private NoticeMapper noticeMapper;


    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        String userId = session.getUri().getQuery();
        this.id = userId;
        sessionMap.put(userId, session);
        log.info("用户【{}】已上线", id);
        log.info("在线用户：{}", sessionMap.toString());
    }

    /**
     *
     * @param session
     * @param message 0: 关注通知
     *                1: 点赞通知
     *                2: 评论通知
     *                3: 用户消息
     * @throws Exception
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        log.info("用户：【{}】，发送消息：【{}】", this.id, message.getPayload());
        this.sendMessageToUser(message);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        log.info("用户【{}】下线", this.id);
        sessionMap.remove(this.id);
    }

    /**
     * 系统通知（点赞、评论、关注）
     * @param from  消息来源
     * @param target  消息接收者
     * @param type  消息类型
     * @param content   消息内容
     */
    @Transactional
    public void sendMessage(String from, String target, String type, String content, String bzicId) {
        Map<String, String> userInfoById = userMapper.getUserInfoById(from);
        JSONObject msgObj = new JSONObject();
        if(ObjectUtils.isNotEmpty(sessionMap.get(target))) {
            msgObj.put("type", type);
            msgObj.put("nickname", userInfoById.get("nickname"));
            msgObj.put("avatar", userInfoById.get("avatar"));
            msgObj.put("content", content);
            msgObj.put("from", from);
            try {
                sessionMap.get(target).sendMessage(new TextMessage(msgObj.toJSONString()));
                log.info("消息发送完毕");
            } catch (IOException e) {
                log.error("发送失败：{}", e);
            }
        }
        String id = UUID.randomUUID().toString().replaceAll("\\-", "");
        noticeMapper.addNoticeLog(id, type, target, from, "0", bzicId);
    }

    /**
     * 用户聊天
     * @param message  消息体 含发送者、接收者、内容
     */
    @Transactional
    public void sendMessageToUser(TextMessage message) {
        Map<String, String>  msg = JSONObject.parseObject(message.getPayload(), Map.class);
        String target = msg.get("target");
        String type = msg.get("type");
        String content = msg.get("content");
        String time = msg.get("time");
        String source = msg.get("from");
        JSONObject msgObj = new JSONObject();
        if(ObjectUtils.isNotEmpty(sessionMap.get(target))) {
            Map<String, String> userInfoById = SpringBeanUtils.userMapper.getUserInfoById(this.id);
            msgObj.put("nickname", userInfoById.get("nickname"));
            msgObj.put("avatar", userInfoById.get("avatar"));
            msgObj.put("type", type);
            msgObj.put("content", content);
            msgObj.put("from", source);
            msgObj.put("time", time);
            log.info("消息体：{}", msgObj.toString());
            try {
                sessionMap.get(target).sendMessage(new TextMessage(msgObj.toJSONString()));
                log.info("消息发送完毕");
            } catch (IOException e) {
                log.error("消息发送失败：{}", e);
            }
        }else {
            log.warn("用户【{}】离线", target);
        }
        Message msgEntity = new Message();
        msgEntity.setTarget(target);
        msgEntity.setSource(source);
        msgEntity.setBody(content);
        SpringBeanUtils.messageService.saveMessage(msgEntity);
    }
}
